package com.tvunetworks.center.device.service.impl;

import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.common.exception.ServerException;
import com.tvunetworks.center.device.constant.DeviceConstant;
import com.tvunetworks.center.device.mapper.DeviceExtraMapper;
import com.tvunetworks.center.device.model.DeviceExtra;
import com.tvunetworks.center.device.model.MyDevice;
import com.tvunetworks.center.device.model.param.SetManualParam;
import com.tvunetworks.center.device.model.result.ResultConstant;
import com.tvunetworks.center.device.service.DeviceExtraService;
import com.tvunetworks.center.device.service.DeviceService;
import com.tvunetworks.center.device.service.MyDeviceService;
import com.tvunetworks.center.device.util.RedisUtil;
import com.tvunetworks.center.gs.model.Device;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @program: tvucc-aggregator
 * @description: DeviceExtraServiceImpl
 * @author lebronchen
 * @create: 2020-03-13 08:10
 **/
@Service
@Slf4j
public class DeviceExtraServiceImpl extends BaseService<DeviceExtra> implements DeviceExtraService {

    @Autowired
    private MyDeviceService myDeviceService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private DeviceExtraMapper deviceExtraMapper;

    @Value("${redisKey.deviceManual}")
    private String deviceManualKey;
    @Value("${redisKey.autoDevices}")
    private String autoDevicesKey;
    @Value("${redisTTL.deviceManual}")
    private long deviceManualTTL;

    @Override
    @Transactional
    public void addDeviceExtra(String peerId, String key, String value) {
        MyDevice myDevice = myDeviceService.getDeviceByPeerId(peerId);
        if (myDevice == null) {
            ServerException.Exception(ResultConstant.Device.DEVICE_NOT_EXIST);
        }
        DeviceExtra deviceExtra = this.getDeviceExtra(peerId, key);
        if (deviceExtra != null) {
            deviceExtra.setValue(value);
            super.update(deviceExtra);
        } else {
            DeviceExtra record = new DeviceExtra()
                    .setPeerId(peerId)
                    .setKey(key)
                    .setValue(value);
            super.insert(record);
        }
    }

    @Override
    public DeviceExtra getDeviceExtra(String peerId, String key) {
        DeviceExtra record = new DeviceExtra()
                .setPeerId(peerId)
                .setKey(key);
        return super.selectExistOne(record);
    }

    @Override
    @Transactional
    public void setManual(SetManualParam param) {
        List<String> peerIds = param.getPeerIds();
        if (CollectionUtils.isEmpty(peerIds)) {
            return;
        }
        List<Device> devices = deviceService.listCurrentDevice(peerIds);
        if (CollectionUtils.isEmpty(devices)) {
            return;
        }
        List<String> livingPeerIds = devices.stream().filter(item -> LocalConstant.DeviceStatus.LIVING.equals(item.getStatus())).map(Device::getPeerId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(livingPeerIds)) {
            ServerException.Exception(ResultConstant.Customized.AutoDevice.EXIST_CHANNEL_OCCUPY);
        }
        for (Device device : devices) {
            String peerId = device.getPeerId();
            if (!LocalConstant.DeviceType.R.equals(device.getType())) {
                log.error("Customized CC setManual device not R peerId:{} type:{}", peerId, device.getType());
                continue;
            }

            String manual = "1".equals(param.getManual()) ? "1" : "0";
            this.addDeviceExtra(peerId, DeviceConstant.DeviceExtra.MANUAL, manual);

            redisUtil.delete(deviceManualKey + peerId);
        }
        redisUtil.delete(autoDevicesKey);
    }

    @Override
    public boolean isDeviceManual(String peerId) {
        peerId = peerId.toLowerCase();
        String manual = (String)redisUtil.get(deviceManualKey + peerId);
        if (manual != null) {
            return "1".equals(manual);
        }
        DeviceExtra record = new DeviceExtra()
                .setPeerId(peerId)
                .setKey(DeviceConstant.DeviceExtra.MANUAL);
        DeviceExtra extra = super.selectExistOne(record);
        if (extra == null) {
            manual = "1";
        } else {
            manual = extra.getValue();
        }

        redisUtil.set(deviceManualKey + peerId, manual, deviceManualTTL);

        return "1".equals(manual);
    }

    @Override
    public List<String> listCacheAutoPeerIds() {
        List<String> autoPeerIds = (List<String>)redisUtil.get(autoDevicesKey);
        if (autoPeerIds != null) {
            return autoPeerIds;
        }
        autoPeerIds = deviceExtraMapper.listAutoPeerIds(DeviceConstant.DeviceExtra.MANUAL);
        redisUtil.set(autoDevicesKey, autoPeerIds, deviceManualTTL);
        return autoPeerIds;
    }

    @Override
    public List<String> listAutoPeerIds() {
        List<String> autoPeerIds = deviceExtraMapper.listAutoPeerIds(DeviceConstant.DeviceExtra.MANUAL);
        return autoPeerIds;
    }

}
